#include "cspline.h"
#include <gsl/gsl_spline.h>
#include <malloc.h>
#include <assert.h>



struct cspline * cspline_init(uint8_t * status, double * xx, double * yy, uint32_t N){
	struct cspline * cs = malloc(sizeof(struct cspline));
	if(NULL == cs){
		* status = 1;
		return NULL;
	}
	// Setting refcnt
	cs -> refcnt = 1;
	// Copying data pointers
	cs -> xx = xx;
	cs -> yy = yy;
	// Data length
	cs -> N = N;
	// Initialising interpolator
	cs -> interp = gsl_interp_alloc(gsl_interp_cspline, N);
	if(NULL == cs -> interp){
		free(cs);
		* status = 1;
		return NULL;
	}
	if(gsl_interp_init(cs -> interp, cs -> xx, cs -> yy, cs -> N)){
		// Could not initialise interpolator
		gsl_interp_free(cs -> interp);
		free(cs);
		* status = 2;
		return NULL;
	}
	* status = 0;
	return cs;
}

void cspline_notify_copied(struct cspline * cs){
	cs -> refcnt += 1;
}


void cspline_free(struct cspline * cs){
	assert(cs -> refcnt > 0);//Someone calls us, so at least the subject 
	//was owning our pointer
	cs -> refcnt -= 1;
	if( ! cs -> refcnt ){
		// Deconstructing the whole
		gsl_interp_free(cs -> interp);
		free(cs -> xx);
		free(cs -> yy);
		free(cs);
	}
}



int cspline_calculate(const struct cspline * cs, double x, double * y){
	int eval_status = gsl_interp_eval_e(cs -> interp, cs -> xx, cs -> yy, x, NULL, y);// NULL - we don't use accelerator
	return eval_status;
}
